home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Source Code
/
Libraries
/
Graphic Elements 3
/
GEDemo
/
Cannon.c
next >
Wrap
Text File
|
1995-08-25
|
6KB
|
225 lines
/*
Cannon.c
Cannon scene for GEDemo
Copyright 1993 by Al Evans. All rights reserved.
11/3/93
*/
#include "Cannon.h"
#include "Rects.h"
#include "Motion.h"
#include "SFXCtrlr.h"
#include "SFXProcs.h"
#include "GESound.h"
//static MotionParams ballMotion;
pascal void DisposeBall(GEWorldPtr world, GrafElPtr element)
{
if (element->drawData)
DisposPtr(element->drawData);
if (element->changeData)
DisposPtr(element->changeData);
}
Boolean LoadCannonScene(GEWorldPtr world)
{
GrafElPtr cannon, thisElement;
short smokeWidth, smokeHeight;
MotionParams *ballMotion;
//Get cannon picture
cannon = NewBasicPICT(world, cannonID, cannonPlane, rCannonPic,
transparent, cannonLeft, cannonTop);
if (cannon == nil) return false;
//Get cannonball picture
thisElement = NewBasicPICT(world, ballID, ballPlane, rBallPic,
transparent, cannonLeft - 8, cannonTop - 8);
if (thisElement == nil) return false;
//Draw cannonball masked
thisElement->drawData = MakeMask(&((GrafPtr) thisElement->graphWorld)->portBits, 0);
thisElement->copyMode = srcCopy;
//Be sure to Dispose Mask & motion params
SetCleanupProc(world, ballID, DisposeBall);
//Initialize motion parameters
ballMotion = (MotionParams *) NewPtr(sizeof(MotionParams));
ballMotion->limitRect = world->animationRect;
RectOffset(&ballMotion->limitRect, 0, ScaleToWorld(world,-80));
InitMotion(ballMotion, 2, 90);
//Initialize cannonball's motion
SetAutoChange(world, ballID, DoCannonBall, (Ptr) ballMotion, 33);
//Initialize cannonball's collision params
SetCollision(world, ballID, DoBallHit, 650);
//Cannonball is initially invisible
ShowElement(world, ballID, false);
//Get animated smoke picture
thisElement = NewAnimatedGraphic(world, smokeID, smokePlane, rSmokePic,
transparent, 0, 0, 3);
if (thisElement == nil) return false;
//Position smoke in relation to cannon
smokeWidth = RectWidth(&thisElement->graphRect);
smokeHeight = RectHeight(&thisElement->graphRect);
PtrMoveElementTo(world, thisElement, ScaleToWorld(world, cannonLeft + 16) - smokeWidth,
ScaleToWorld(world, cannonTop + 16) - smokeHeight, false);
//Set smoke animation
AnimateGraphic(world, smokeID, 170, oneshotvanish);
//Smoke is initially invisible
ShowElement(world, smokeID, false);
//Smoke is attached to cannon
cannon->slaveGrafEl = thisElement;
//Get "FIRE" button
thisElement = NewButtonSensor(world, fBtnID, btnPlane, rFBtnPic, 434, 193);
if (thisElement == nil) return false;
SetSensorAction(world, fBtnID, ShootCannon);
return true;
}
pascal void DoCannonBall(GEWorldPtr world, GrafElPtr ball)
{
MParamPtr motion;
motion = (MParamPtr) ball->changeData;
if ((motion->currMotion.v == 0) && (motion->currMotion.h == 0)) {
(void) DoGESFX(world, 'SFXB', ball, SFXVWipe,
RectHeight(&ball->animationRect), 0, 200, false, true);
return;
}
MoveElement(world, ball->objectID, motion->currMotion.h, motion->currMotion.v);
switch (CheckLimits(&ball->animationRect, &motion->limitRect)) {
case down:
if (motion->currMotion.v > 0) {
if (world->userData != nil)
GEScheduleSound((GESoundPtr) world->userData, rBallSnd, 1, 0);
DoBounce(v, motion);
}
DoFriction(motion);
break;
case right:
if (motion->currMotion.h > 0) {
if (world->userData != nil)
GEScheduleSound((GESoundPtr) world->userData, rBallSnd, 1, 0);
DoBounce(h, motion);
}
break;
case left:
if (motion->currMotion.h < 0) {
if (world->userData != nil)
GEScheduleSound((GESoundPtr) world->userData, rBallSnd, 1, 0);
DoBounce(h, motion);
}
break;
default:
motion->currMotion.v++;
break;
}
}
pascal void DoBallHit(GEWorldPtr world, GrafElPtr ball,
GEDirection dir, CollisionPhase phase, GrafElPtr objHit)
{
MParamPtr motion;
if (phase == collisionBegin) {
motion = (MParamPtr) ball->changeData;
switch (dir) {
case left:
if (motion->currMotion.h < 0)
DoBounce(h, motion);
break;
case right:
if (motion->currMotion.h > 0)
DoBounce(h, motion);
break;
case up:
if (motion->currMotion.v < 0)
DoBounce(v, motion);
break;
case down:
if (motion->currMotion.v > 0)
DoBounce(v, motion);
break;
case upLeft:
if (motion->currMotion.v < 0)
DoBounce(v, motion);
if (motion->currMotion.h < 0)
DoBounce(h, motion);
break;
case downLeft:
if (motion->currMotion.v > 0)
DoBounce(v, motion);
if (motion->currMotion.h < 0)
DoBounce(h, motion);
break;
case upRight:
if (motion->currMotion.v < 0)
DoBounce(v, motion);
if (motion->currMotion.h > 0)
DoBounce(h, motion);
break;
case downRight:
if (motion->currMotion.v > 0)
DoBounce(v, motion);
if (motion->currMotion.h > 0)
DoBounce(h, motion);
break;
}
if (FindElementByID(world, 'SFXP') == nil) //One at a time, please
{
if (world->userData != nil)
GEScheduleSound((GESoundPtr) world->userData, rHitSnd, 1, 0);
(void) DoGESFX(world, 'SFXP', objHit, SFXBlink, 10, 0, 50, true, true);
}
}
}
pascal void ShootCannon(GEWorldPtr world, GrafElPtr ignore, short fireIt)
{
GrafElPtr cannon, ball;
MParamPtr ballMotion;
#pragma unused (fireIt)
cannon = FindElementByID(world, cannonID);
if (cannon) {
ball = FindElementByID(world, ballID);
if (ball) {
ballMotion = (MParamPtr) ball->changeData;
ballMotion->currMotion.h = -20;
ballMotion->currMotion.v = -20;
ballMotion->frictAcc = 0;
PtrMoveElementTo(world, ball, cannon->animationRect.left - ScaleToWorld(world, 8),
cannon->animationRect.top - ScaleToWorld(world, 8), false);
ShowElement(world, ballID, true);
}
if (world->userData != nil)
GEScheduleSound((GESoundPtr) world->userData, rFireSnd, 1, 0);
ShowElement(world, smokeID, true);
}
}